from typing import Optional
import numpy as np
from pydantic import BaseModel
import pandas as pd

class Kline(BaseModel):
    Open: Optional[str] = ''
    Close: Optional[str] = ''
    High: Optional[str] = ''
    Low: Optional[str] = ''
    Volume: Optional[str] = ''
    OpenTime: Optional[str] = ''
    CloseTime: Optional[str] = ''
    TakerBuyBaseVolume: Optional[str] = ''

class Indicator:
    def __init__(self, kline: list[Kline]):
       self.kline = kline or []
       self.closes = [float(item['Close']) for item in self.kline]
       self.volume = [float(item['Volume']) for item in self.kline]
       self.TakerBuyBaseVolume = [float(item['TakerBuyBaseVolume']) for item in self.kline]

    def MA_line(self, period=5, type='Close'):
        if type == 'Volume':
            if len(self.volume) < period:
                return None
            return sum(self.volume[-period:]) / period
        else:
            if len(self.closes) < period:
                return None
            return sum(self.closes[-period:]) / period

    def RSI_line(self, period=6):
        if len(self.closes) < period + 1:
            return None
        delta = pd.Series(self.closes).diff()
        gain = delta.where(delta > 0, 0.0)
        loss = -delta.where(delta < 0, 0.0)

        avg_gain = gain.rolling(window=period).mean()
        avg_loss = loss.rolling(window=period).mean()

        rs = avg_gain / avg_loss
        rsi = 100 - (100 / (1 + rs))
        return rsi

    def cross_line(self, short_period=7, long_period=25, slope=0.001):
        if len(self.closes) < long_period + 1:
            return None  # 数据不足
        def ma_line(closes, period):
            if len(closes) < period:
                return None
            return sum(closes[-period:]) / period
        # 当前和前一周期的短期MA
        short_ma_prev = ma_line(self.closes[:-1], short_period)
        short_ma_now = ma_line(self.closes, short_period)
        short_slope = 1 - slope

        # 当前和前一周期的长期MA
        long_ma_prev = ma_line(self.closes[:-1], long_period)
        long_ma_now = ma_line(self.closes, long_period)
        long_slope = 1 + slope

        # 判断金叉和死叉
        if short_ma_prev < long_ma_prev * long_slope and short_ma_now > long_ma_now * long_slope:
            return "golden_cross"  # 金叉
        elif short_ma_prev > long_ma_prev * short_slope and short_ma_now < long_ma_now * short_slope:
            return "death_cross"   # 死叉
        else:
            return "no_signal"